package com.tanx.cqrs.spring.boot.autoconfig;

import com.tanx.cqrs.command.CommandBus;
import com.tanx.cqrs.command.handler.CommandHandlerResolver;
import com.tanx.cqrs.event.EventBus;
import com.tanx.cqrs.event.RoutingKeyGenerator;
import com.tanx.cqrs.event.handler.EventHandlerResolver;
import com.tanx.cqrs.infrastructure.spring.command.MemoryCommandBus;
import com.tanx.cqrs.infrastructure.spring.event.PackageRoutingKeyGenerator;
import com.tanx.cqrs.infrastructure.spring.event.RabbitMqEventBus;
import com.tanx.cqrs.infrastructure.spring.event.handler.EventHistoryHandler;
import com.tanx.cqrs.infrastructure.spring.event.store.EventStoreRepositoryFactory;
import com.tanx.cqrs.infrastructure.util.CommandSender;
import com.tanx.cqrs.infrastructure.util.EventSender;
import com.tanx.cqrs.saga.SagaHandlerResolver;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
 * spring boot的自动配置
 */
@Configuration
@ConditionalOnClass({CommandBus.class, EventBus.class})
@EnableConfigurationProperties(SpringRabbitProperties.class)
@ComponentScan(basePackages = {"com.tanx.cqrs", "com.tanx.cqrs.infrastructure.spring",
        "com.tanx.cqrs.infrastructure.spring.command"})
@EnableScheduling
@Import({SpringAnnotationDrivenConfiguration.class, MongoAnnotationDrivenConfiguration.class})
public class CqrsAutoConfiguration {

    @ConditionalOnClass(CommandBus.class)
    @ConditionalOnMissingBean(value = {CommandBus.class})
    @Bean
    public CommandBus commandBus(CommandHandlerResolver resolver) {
        MemoryCommandBus memoryCommandBus = new MemoryCommandBus(resolver);
        CommandSender.BUS = memoryCommandBus;
        return memoryCommandBus;
    }

    @ConditionalOnClass(EventBus.class)
    @ConditionalOnMissingBean(value = {EventBus.class})
    @Bean
    public EventBus eventBus(EventHandlerResolver eventHandlerResolver, SagaHandlerResolver sagaHandlerResolver
            , RoutingKeyGenerator keyGenerator, SpringRabbitProperties properties, EventStoreRepositoryFactory factory) {
        RabbitMqEventBus rabbitMqEventBus = new RabbitMqEventBus(eventHandlerResolver, sagaHandlerResolver, keyGenerator, properties, factory);
        rabbitMqEventBus.receiveEvent();
        EventSender.BUS = rabbitMqEventBus;
        return rabbitMqEventBus;
    }

    @ConditionalOnClass(RoutingKeyGenerator.class)
    @ConditionalOnMissingBean(value = {RoutingKeyGenerator.class})
    @Bean
    public RoutingKeyGenerator routingKeyGenerator() {
        return new PackageRoutingKeyGenerator();
    }

    @ConditionalOnClass(EventHistoryHandler.class)
    @ConditionalOnMissingBean(value = {EventHistoryHandler.class})
    @Bean
    public EventHistoryHandler eventHistoryHandler(ApplicationContext context, EventBus eventBus) {
        EventHistoryHandler eventHistoryHandler = new EventHistoryHandler(context, eventBus);
        eventHistoryHandler.registerAllHandler();
        return eventHistoryHandler;
    }

}
